Passed
Branchmaster (c55ea7)
by Plamen
01:24
created

table.js ➔ ... ➔ RequestToUrl   A

Complexity

Conditions 5
Paths 2

Size

Total Lines 17
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 13
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 17
rs 9.2833
1
var TableHelperRequestSort = function(rq, strDesc){
2
    function sortBySpan(span, i){
3
        var order = span.innerHTML;
4
        if(order.length === 1){
5
            rq.colNo = i;
6
            rq.colOrd = order === strDesc ? "desc" : "asc";
7
        }
8
        return rq.colNo === i;
9
    }
10
    
11
    var thTags = document.getElementById(rq.tableId)
12
            .getElementsByTagName("thead")[0]
13
            .getElementsByTagName("th");
14
    var length = thTags.length;
15
    for(var i = 0; i < length; i++){
16
        var link = thTags[i].getElementsByTagName("a")[0];
17
        if(link){
18
            var span = link.getElementsByTagName("span")[0];
19
            if(span && sortBySpan(span, i)){
20
                break;
21
            }
22
        }
23
    }
24
};
25
var TableHelperRequestFilter = function(rq){
26
    function getFilterFieldsByTableID(tableID){
27
        var fields = {filterBy: null, filter: null};
28
        var filterDiv = getFilterDivByTableIDOrNull(tableID);
29
        if(filterDiv !== null){
30
            setFilterBy(fields, filterDiv);
31
            setFilterValue(fields, filterDiv);
32
        }
33
        return fields;
34
    }
35
    function getFilterDivByTableIDOrNull(tableID){
36
        var res = null;
37
        if(document.getElementById(tableID).parentNode.getElementsByTagName("div").length > 0){
38
            for(var i = 0; i < document.getElementById(tableID).parentNode.getElementsByTagName("div").length; i++){
39
                if(document.getElementById(tableID).parentNode.getElementsByTagName("div")[i].getAttribute("class") === "filter"){
40
                    return document.getElementById(tableID).parentNode.getElementsByTagName("div")[i];
41
                }
42
            }
43
44
        }
45
        return res;
46
    }
47
    function setFilterBy(fields, filterDiv){
48
        var slctObj = filterDiv.getElementsByTagName("select")[0];
49
        if(slctObj && slctObj.options[slctObj.selectedIndex].value !== "all"){
50
            fields.filterBy = slctObj.options[slctObj.selectedIndex].value;
51
        }
52
    }
53
    function setFilterValue(fields, filterDiv){
54
        var textObj = filterDiv.getElementsByTagName("input")[0];
55
        if(textObj && textObj.value && textObj.value.length !== 0){
56
            fields.filter = encodeURIComponent(textObj.value.trim());
57
        }
58
    }
59
60
    var r = getFilterFieldsByTableID(rq.tableId);
61
    if(r.filter !== null){
62
        rq.filter = r.filter;
63
    }
64
    if(r.filterBy !== null){
65
        rq.filterBy = r.filterBy;
66
    }
67
};
68
var TableHelperColumnHover = function(tableContainer, index){
69
    var rows = document.getElementById(tableContainer).rows;
70
    var upto = rows.length - 1;
71
    if(typeof index === "undefined"){
72
        TableHelperColumnHoverRelease(rows, upto);
73
    } else {
74
        for(var i = 0; i < upto; i++){
75
            rows[i].cells[index].setAttribute("lang", "col-hover");
76
        }
77
    }
78
};
79
var TableHelperColumnHoverRelease = function(rows, upto){
80
    for(var i = 0; i < upto; i++){
81
        for(var j = 0; j < rows[i].cells.length; j++){
82
            if(rows[i].cells[j].lang){
83
                rows[i].cells[j].removeAttribute("lang");
84
            }
85
        }
86
    }
87
};
88
var TableHelperSetVisability = function(tableContainer, flag){
89
    var tbl = document.getElementById(tableContainer);
90
    if(flag === true){
91
        tbl.style.filter = "none";
92
        tbl.style.opacity = "1";
93
        tbl.style.cursor = "auto";
94
    }else if(flag === false){
95
        tbl.style.filter = "blur(1px)";
96
        tbl.style.opacity = "0.8";
97
        tbl.style.cursor = "wait";
98
    }else{
99
        console.error("table error in the flag value");
100
    }
101
};
102
var TableHelperProcessPaginationLinks = function(tfoot){
103
    var pLinks = tfoot.querySelectorAll(".paging a");
104
    if(pLinks.length > 0){
105
        for(var j = 0; j < pLinks.length; j++){
106
            pLinks[j].setAttribute("href", "javascript:void(0);");
107
            pLinks[j].setAttribute("onclick", "return table.GoPage(this);");
108
        }
109
    }
110
};
111
var TableHelperIfPrior = function(v){
112
    var rv = false;
113
    if(window.navigator.appName === 'Microsoft Internet Explorer'){
114
        var ua = window.navigator.userAgent;
115
        var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
116
        if(re.exec(ua) !== null){
117
            rv = parseFloat(RegExp.$1);
118
        }
119
        rv = rv < v ? true : false;
120
    }
121
    return rv;
122
};
123
var TableHelperRequestToUrl = function(rq){
124
    var url = location.pathname + ".json" + location.search;
125
    if(typeof rq === "object"){
126
        var getUrlVarName = {
127
            colNo: "col", colOrd: "ord", filter: "filter",
128
            filterBy: "filter-by", pageNo: "pg", exportType: "export",
129
            tableId: "table-id"
130
        };
131
        var flagFirst = location.search.length < 1 ? true : false;
132
        for(var r in rq){
1 ignored issue
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
133
            var clue = flagFirst === true ? "?" : "&";
134
            url += clue + getUrlVarName[r] + "=" + rq[r];
135
            flagFirst = false;
136
        }
137
    }
138
    return url;
139
};
140
141
//https://addyosmani.com/resources/essentialjsdesignpatterns/book/#singletonpatternjavascript
142
var TableSingleton = (function(){
143
    // Instance stores a reference to the Singleton
144
    var instance;
145
    function initInstance(){
146
        // Singleton
147
        // Private methods and variables
148
        function BuildRequest(rq, crntTableId){
149
            rq.tableId = crntTableId;
150
            TableHelperRequestSort(rq, instance.strDesc);
151
            TableHelperRequestFilter(rq);
152
        }
153
        function getParent(obj, objType){
154
            while(obj && obj.tagName !== objType.toUpperCase()){
155
                obj = obj.parentNode;
156
            }
157
            return obj;
158
        }
159
        function FilterGetTableId(field){
160
            if(field.tagName.toLowerCase() !== "select"){
161
                return field.getAttribute("data-table-id");
162
            }
163
            var f = field.parentNode.parentNode.getElementsByTagName("input")[0];
164
            return '' === f.value ? null : f.getAttribute("data-table-id");
165
        }
166
        var tail = [];
167
        function LoadData(tableContainer, rq){
168
            SetVisability(tableContainer, false);
169
            if(window.XMLHttpRequest){
170
                var xmlhttp = new XMLHttpRequest();/* code for IE7+, Firefox, Chrome, Opera, Safari */
171
            }else{ 
172
                xmlhttp = new window.ActiveXObject("Microsoft.XMLHTTP");/*code for IE6, IE5 */
173
            }
174
            for(var i = 0; i < tail.length; i++){
175
                var ex_xmlhttp = tail.shift();
176
                ex_xmlhttp.abort();
177
            }
178
            xmlhttp.onreadystatechange = function(){
179
                if(xmlhttp.readyState === 4 && xmlhttp.status === 200){
180
                    var d = JSON.parse(xmlhttp.responseText);
181
                    instance.rq = rq;
182
                    instance.Draw(tableContainer, d);
183
                }
184
            };
185
            xmlhttp.open("GET", RequestToUrl(rq), true);
186
            xmlhttp.send();
187
            tail.push(xmlhttp); //put at tail to can abort later any previous
188
        }
189
        function clearSection(tSection){
190
            if(iePrior(9)){
191
                if(tSection.firstChild){
192
                    while(tSection.firstChild){
193
                        tSection.removeChild(tSection.firstChild);
194
                    }
195
                }
196
            }else{
197
                tSection.innerHTML = "";
198
            }
199
        }
200
        function SetTheTableColumnsHoverEffect(tableContainer){
201
            if(iePrior(9)){
202
                return;
203
            }
204
            var tContainer = document.getElementById(tableContainer);
205
            var tHcells = tContainer.rows[0].cells;
206
            for(var i = 0; i < tHcells.length; i++){
207
                if(tHcells[i].firstChild.tagName === "A"){
208
                    tHcells[i].firstChild.setAttribute("onmouseover", "table.ColumnHover('" + tableContainer + "'," + i + ");");
209
                    tHcells[i].firstChild.setAttribute("onmouseout", "table.ColumnHover('" + tableContainer + "');");
210
                }
211
            }
212
            var tfoot = tContainer.getElementsByTagName("tfoot")[0];
213
            ProcessPaginationLinks(tfoot);
214
        }
215
        var iePrior = TableHelperIfPrior;
216
        var ProcessPaginationLinks = TableHelperProcessPaginationLinks;
217
        var SetVisability = TableHelperSetVisability;
218
        var RequestToUrl = TableHelperRequestToUrl;
219
        
220
        return {
221
            rq: null,
222
            strAsc: String.fromCharCode(9650), //&#9650;
223
            strDesc: String.fromCharCode(9660),//&#9660; 
224
            ReloadData: function(tableId){
225
                var request = {};
226
                BuildRequest(request, tableId);
227
                LoadData(tableId, request);
228
            },
229
            Filter: function(field){
230
                var crntTableId = FilterGetTableId(field);
231
                if(crntTableId !== null){
232
                    var request = {};
233
                    var exRq = this.rq;
234
                    BuildRequest(request, crntTableId);
235
                    if(exRq === null ||
236
                        request.filter !== exRq.filter ||
237
                        request.filterBy !== exRq.filterBy
238
                    ){
239
                        LoadData(crntTableId, request);
240
                    }
241
                }
242
            },
243
            GoPage: function(lnk){
244
                var request = {};
245
                var table = getParent(lnk, "table");
246
                var crntTableId = table.getAttribute("id");
247
                BuildRequest(request, crntTableId);
248
                //check & serve pagination jump links
249
                var jumpDir = lnk.innerHTML.trim().substr(0, 1);
250
                if(jumpDir === "+" || jumpDir === "-"){
251
                    var current = table.querySelector("tfoot .paging .a").innerHTML;
252
                    var jump = lnk.innerHTML.replace("K", "000").replace("M", "000000000");
253
                    var jumpPage = (parseInt(current) + parseInt(jump));
254
                    lnk.parentNode.setAttribute("data-page", jumpPage);
255
                    lnk.style.transform = "none";
256
                }
257
                request.pageNo = lnk.parentNode.hasAttribute("data-page") ?
258
                                    lnk.parentNode.getAttribute("data-page") :
259
                                    lnk.innerHTML;
260
                LoadData(crntTableId, request);
261
                return false;
262
            },
263
            Export: function(lnk, eType){
264
                var request = {};
265
                var crntTableId = getParent(lnk, "table").getAttribute("id");
266
                BuildRequest(request, crntTableId);
267
                request.exportType = ["CSV", "Excel"].indexOf(eType) >= 0 ?
268
                                        eType : 
269
                                        "csv";
270
                window.open(RequestToUrl(request));
271
                return false;
272
            },
273
            Sort: function(colNo, lnk){
274
                var request = {};
275
                var crntTableId = getParent(lnk, "table").getAttribute("id");
276
                BuildRequest(request, crntTableId);
277
                if(Math.round(colNo) === request.colNo){
278
                    request.colOrd = (request.colOrd === "asc" ? "desc" : "asc");
279
                }else{
280
                    request.colNo = Math.round(colNo);
281
                    request.colOrd = "asc";
282
                }
283
                LoadData(crntTableId, request);
284
                /* Clear and add new sort arrow */
285
                var headSpans = getParent(lnk, "thead").getElementsByTagName("span");
286
                var length = headSpans.length;
287
                for(var i = 0; i < length; i++){
288
                    headSpans[i].innerHTML = "";
289
                }
290
                lnk.getElementsByTagName("span")[0].innerHTML = (request.colOrd === "desc" ? this.strDesc : this.strAsc);
291
            },
292
            DrawSection: function(tableContainer, dt, tSection){
293
                var section = tSection === "tfoot" ? "tfoot" : "tbody";
294
                tSection = document.getElementById(tableContainer).
295
                            getElementsByTagName(section)[0];
296
                clearSection(tSection);
297
                for(var i = 0; i < dt.length; i++){
298
                    var row = dt[i];
299
                    var tRow = document.createElement("tr");
300
301
                    this.DrawRow(row, tRow);
302
303
                    tSection.appendChild(tRow);
304
                    if(section === "tfoot"){
305
                        ProcessPaginationLinks(tSection);
306
                    }
307
                    this.AppendRowCalback(tableContainer);
308
                }
309
            },
310
            DrawRow: function(row, tRow){
311
                for(var cell in row){
1 ignored issue
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
312
                    var tCell = document.createElement("td");
313
                    if(typeof row[cell] === "string" || typeof row[cell] === "number"){
314
                        tCell.innerHTML = row[cell];
315
                    }else if(typeof row[cell] === "object"){
316
                        this.DrawCellFromObject(row, cell, tCell);
317
                    }
318
                    tRow.appendChild(tCell);
319
                }
320
            },
321
            DrawCellFromObject: function(row, cell, tCell){
322
                for(var attr in row[cell]){
1 ignored issue
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
323
                    if(typeof row[cell][attr] === "string"){
324
                        tCell.innerHTML = row[cell][attr];
325
                    }else if(typeof row[cell][attr] === "object"){
326
                        for(var v in row[cell][attr]){
1 ignored issue
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
327
                            tCell.setAttribute(v, row[cell][attr][v]);
328
                        }
329
                    }
330
                }
331
            },
332
333
            ColumnHover: function(tableContainer, index){
334
                if(!iePrior(9)){
335
                    TableHelperColumnHover.call(this, tableContainer, index);
336
                }
337
            },
338
            Draw: function(tableContainer, d){
339
                this.DrawSection(tableContainer, d.body);
340
                this.DrawSection(tableContainer, d.footer, "tfoot");
341
                this.LoadEndCalback(tableContainer);
342
                SetVisability(tableContainer, true);
343
                if(this.rq !== null){
344
                    var hover = document.getElementById(this.rq.tableId)
345
                                .getElementsByTagName("th")[this.rq.colNo].lang;
346
                    if(hover){
347
                        this.ColumnHover(tableContainer, this.rq.colNo);
348
                    }
349
                }
350
                
351
            },
352
            init: function(tableId){
353
                SetTheTableColumnsHoverEffect(tableId);
354
            },
355
            LoadEndCalback: function(){},/*Allows override: function(tableId){if(tableId){...}}*/
356
            AppendRowCalback:  function(){}/*Allows override: function(tableId){if(tableId){...}}*/
357
        };
358
    }
359
    return {
360
        //Get the Singleton instance if one exists, or create one if it doesn't
361
        getInstance: function(){
362
            if(!instance){
363
                instance = initInstance();
364
            }
365
            return instance;
366
        }
367
    };
368
})();
369
var table = TableSingleton.getInstance();
370